#include "BaseEntity.h"
#include "EntityManager.h"

//typedef void (BaseEntity::*InputFunc)(BaseEntity* ent);

BaseEntity::BaseEntity(sf::RenderWindow *App)
{
	DeleteMe = false;
	if (App != NULL)
	{
		pRender = App;
	}
	DrawOrder = 1;
	Angle = 0;
	PhysicsEnabled = false;
	MatrixNeedsUpdate = true;
	mOwner = NULL;
	Health = 100.f;
	MaxHealth = 100.f;
	bAlive = true;
}

BaseEntity::~BaseEntity(void)
{
	
}

void BaseEntity::Fire(std::string &Name)
{
	if (Inputs[Name] == NULL)
	{
		std::cout << "Invalid input '" << Name << "' invoked!\n";
		return;
	}
	(*Inputs[Name])(this);
}

void BaseEntity::RegisterInput(std::string &Name, InputFunc Func)
{
	Inputs[Name] = Func;
}


sf::Matrix3 BaseEntity::GetMatrix()
 {
	 if (MatrixNeedsUpdate)
	 {
		 Matrix = sf::Matrix3::Transformation(GetOrigin(), GetPos(), -GetAngle(), sf::Vector2f(1.f,1.f));
		 MatrixNeedsUpdate = false;
	 }
	 return Matrix;
}

sf::Vector2f BaseEntity::ToGlobal(sf::Vector2f &point)
{
	return GetMatrix().Transform(point);
}

sf::Vector2f BaseEntity::ToLocal(sf::Vector2f &point)
{
	return GetMatrix().GetInverse().Transform(point);
}

int BaseEntity::GetMeta(std::string ID)
{
	return MetaData[ID];
}

//All the doubles here are to reduce rounding errors as this is a very sensitive function!
sf::Vector2f BaseEntity::GameCoordsToSFML(sf::Vector2f Pos)
{
	sf::Vector2<double> dPos;
	dPos.x = Pos.x;
	dPos.y = Pos.y;
	dPos.y *= -1;
	sf::Vector2<double> ScreenCentre = sf::Vector2<double>(pRender->GetWidth() / 2, pRender->GetHeight() / 2);
	sf::Vector2<double> ViewCentre;
	ViewCentre.x = pRender->GetView().GetCenter().x;
	ViewCentre.y = pRender->GetView().GetCenter().y;

	dPos = dPos + ViewCentre + (ScreenCentre - ViewCentre);

	Pos.x = dPos.x;
	Pos.y = dPos.y;

	return Pos;
}

sf::Vector2f BaseEntity::SFMLToGameCoords(sf::Vector2f Pos)
{
	Pos = Pos - pRender->GetView().GetCenter();
	Pos.y *= -1;
	return Pos;
}


void BaseEntity::Tick()
{
	if (DeleteMe)
	{
		return;
	}
	if (fNextThink < GameGlobals::Instance()->CurTime)
	{
		fLastThink = GameGlobals::Instance()->CurTime;
		fNextThink = fLastThink + (1.f/60.f); //By default think at 60HZ but child classes can override this
		this->Think();
	}
}

void BaseEntity::Delete(bool Callback)
{
	if (Callback)
		this->OnDelete();
	DeleteMe = true;
}

void BaseEntity::Delete()
{
	this->OnDelete();
	DeleteMe = true;
}